package cn.sunxyz.core.ioc;


import cn.sunxyz.common.falut.InitializationException;
import cn.sunxyz.common.utils.ArrayUtil;
import cn.sunxyz.core.ioc.annotation.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

/**
 * Created by yangrd on 2017/5/19.
 */
class InjectManager {

    private static final Logger logger = LoggerFactory.getLogger(InjectManager.class);

    static void inject(Set<Map.Entry<Class<?>, Object>> entrySet, Function<Field, Object> instanceSearch) {
        logger.debug("[bean inject] :=> start inject");
        for (Map.Entry<Class<?>, Object> entry : entrySet) {
            // 获取 Bean 类与 Bean 实例
            Class<?> beanClass = entry.getKey();
            Object beanInstance = entry.getValue();
            // 获取 Bean 类中所有的字段（不包括父类中的方法）
            Field[] beanFields = beanClass.getDeclaredFields();
            if (ArrayUtil.isNotEmpty(beanFields)) {
                // 遍历所有的 Bean 字段
                for (Field beanField : beanFields) {
                    // 判断当前 Bean 字段是否带有 Inject 注解
                    if (beanField.isAnnotationPresent(Inject.class)) {
                        Class<?> interfaceClass = beanField.getType();
                        // 获取 Bean 字段对应的实现类
                        Object implementInstance = instanceSearch.apply(beanField);
                        if (implementInstance == null) {
                            throw new InitializationException("依赖注入失败！类名：" + beanClass.getSimpleName() + "，字段名：" + interfaceClass.getSimpleName());
                        } else {
                            try {
                                // 设置该 Bean 字段的值
                                if (implementInstance != null) {
                                    beanField.setAccessible(true); // 将字段设置为 public
                                    beanField.set(beanInstance, implementInstance); // 设置字段初始值
                                } else {
                                    throw new InitializationException("依赖注入失败！类名：" + beanClass.getSimpleName() + "，字段名：" + interfaceClass.getSimpleName());
                                }
                            } catch (Exception e) {
                                throw new InitializationException("初始化 InjectManager 出错！", e);
                            }

                        }
                    }
                }
            }
        }
        logger.debug("[bean inject] :=> end inject");
    }
}
